<?php
namespace App\Utils\Arr;

//对象
use App\Utils\Str\Str;


class Target{
    /**
     * 获取对象属性字段列表
     * @param target 对象
     * @return 二维数组
     */
    public static function getProperties($target)
    {
        $reflectionClass = new \ReflectionClass($target);
        $properties = $reflectionClass->getProperties();
        $result = [];
        foreach ($properties as $property) {
            // 获取属性名称
            $key = $property->getName();
            //if($property->getType())
            //获取属性类型名称
            $type = $property->getType()->getName();
            $body = [
              'key'  => $key,
              'type' => $type,
            ];
            $result[] = $body;
        }
        return $result;
    }

    /**
     * 获取对象属性字段key列表
     * @param target 对象
     * @return 一维数组
     */
    public static function getPropertiesKeys($target)
    {
        $data = self::getProperties($target);
        return array_column($data,'key');
    }

    /**
     * 数组转对象
     * @param $source 数组
     * @param $target 对象
     * @return 对象
     */
    public static function copyProperties(array $source,object $target) {
        //反射
        $reflectionClass = new \ReflectionClass($target);
        $properties = $reflectionClass->getProperties();
        foreach ($properties as $property) {
            // 获取属性名称
            $key = $property->getName();
            //if($property->getType())
            //获取属性类型名称
            $type = $property->getType()->getName();
            // 获取属性的类型
            $value = isset($source[$key]) ? $source[$key] : null;

            //注解
            $docComment = $property->getDocComment();
            $annotations = static::parseAnnotations($docComment);

            if (self::isSimpleType($type)) {
                //简单类型
                if($type == "array") {
                    //数组
                    //如果数据是json，自动转数组
                    if ($value) {
                        //有值才判断
                        if (is_string($value) && Str::isJson($value)) {
                            $value = json_decode($value, true);
                        }
                        if (isset($annotations['var'][0])) {
                            if(is_array($value)){
                                $varType = $annotations['var'][0];
                                $varClass = trim(str_replace('[]', '', $varType));
                                foreach ($value as &$item) {
                                    //递归
                                    $obj = new $varClass();
                                    $item = self::copyProperties($item, $obj);
                                }
                                $target->{$key} = $value;
                            }
                        }else{
                            //非注解
                            $target->{$key} = $value;
                        }
                    }elseif(!is_null($value)){
                        $target->{$key} = $value;
                    }else{
                        $target->{$key} = [];
                    }
                }else{
                    if($type == "bool" || $type === 'boolean'){
                        if($value) $target->{$key} = $value;
                    }else{
                        if(!is_null($value)) {
                            $target->{$key} = (string)$value;
                        }
//                        }else{
//                            $target->{$key} = $value;
//                        }
                    }
                }
            } else {
                //对象类型
                if ($value) {
                    //有值才判断
                    if (is_string($value) && Str::isJson($value)) {
                        $value = json_decode($value, true);
                    }
                    //对象处理
                    $obj = new $type();
                    $value = self::copyProperties($value, $obj);
                    $target->{$key} = $value;
                }
            }
        }
        return $target;
    }

    /**
     * 判断是否为简单类型.
     */
    public static function isSimpleType(?string $type): bool
    {
        return $type === 'string'
            || $type === 'boolean' || $type === 'bool'
            || $type === 'integer' || $type === 'int'
            || $type === 'double' || $type === 'float'
            || $type === 'array' || $type === 'object';
    }



    //转注解参数数组
    protected static function parseAnnotations($docblock)
    {
        $annotations = array();
        // Strip away the docblock header and footer
        // to ease parsing of one line annotations
        $docblock = substr($docblock, 3, -2);

        $re = '/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m';
        if (preg_match_all($re, $docblock, $matches)) {
            $numMatches = count($matches[0]);

            for ($i = 0; $i < $numMatches; ++$i) {
                $annotations[$matches['name'][$i]][] = $matches['value'][$i];
            }
        }

        return $annotations;
    }



}